package com.ali.common;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

public class RsaUtil {
    private static final String RSA = "RSA";

    /**
     * 获取公钥与私钥
     */
    public static Map<String, String> getKey() {
        Map<String, String> keyMap = new HashMap<>();

        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA);
            keyPairGenerator.initialize(1024, new SecureRandom());
            KeyPair keyPair = keyPairGenerator.generateKeyPair();

            //获取公钥
            RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
            String publicKey = Base64Util.encrypt(rsaPublicKey.getEncoded());
            keyMap.put("publicKey", publicKey);

            //获取私钥
            RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
            String privateKey = Base64Util.encrypt(rsaPrivateKey.getEncoded());
            keyMap.put("privateKey", privateKey);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return keyMap;
    }

    /**
     * RSA公钥加密
     */
    public static String encrypt(String content, String publicKey) {
        byte[] contentByte = content.getBytes(StandardCharsets.UTF_8);

        try {
            Cipher cipher = Cipher.getInstance(RSA);
            RSAPublicKey rsaPublicKey = getRSAPublicKey(publicKey);
            cipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey);
            byte[] doFinalStrByte = cipher.doFinal(contentByte);
            return Base64Util.encrypt(doFinalStrByte);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取RSAPublicKey
     */
    private static RSAPublicKey getRSAPublicKey(String publicKey) {
        try {
            byte[] publicKeyByte = Base64Util.getByteByDecrypt(publicKey);

            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyByte);
            return (RSAPublicKey) keyFactory.generatePublic(x509EncodedKeySpec);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * RSA私钥解密
     */
    public static String decrypt(String encryptStr, String privateKey) {
        try {
            byte[] encryptStrByte = Base64Util.getByteByDecrypt(encryptStr);

            Cipher cipher = Cipher.getInstance(RSA);
            RSAPrivateKey rsaPrivateKey = getRSAPrivateKey(privateKey);
            cipher.init(Cipher.DECRYPT_MODE, rsaPrivateKey);
            byte[] doFinalStrByte = cipher.doFinal(encryptStrByte);
            return new String(doFinalStrByte, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取RSAPrivateKey
     */
    private static RSAPrivateKey getRSAPrivateKey(String privateKey) {
        try {
            byte[] privateKeyByte = Base64Util.getByteByDecrypt(privateKey);

            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyByte);
            return (RSAPrivateKey) keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}